/*
 * Copyright 2015 泛泛o0之辈
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.jfast.framework.web.api;

import cn.jfast.framework.web.aop.AopHandler;
import cn.jfast.framework.web.aop.annotation.Aop;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * 封装Api动作参数
 */
public class Api {

    /** Api对应类对应路径 */
    private final String typeRoute;
    /** Http请求方法 */
    private final ApiReqMethod apiReqMethod;
    /** Api对应方法对应路径 */
    private final String methodRoute;
    /** Api对应全路径 */
    private final String apiRoute;
    /** Api类名 */
    private final Class<?> api;
    /** Api对应方法 */
    private final Method method;
    /** Api对应方法拦截器链 */
    private final List<Class<? extends AopHandler>> methodAopList;
    /** 全局拦截器链 */
    private final List<Class<? extends AopHandler>> globalAopList;
    private final List<AopHandler> aopList;

    /**
     * 实例化Api对象
     * @param typeRoute
     * @param methodRoute
     * @param api
     * @param method
     * @param apiReqMethod
     * @param methodAopList
     * @param globalAopList
     */
    public Api(String typeRoute,
               String methodRoute,
               Class<?> api,
               Method method,
               ApiReqMethod apiReqMethod,
               List<Class<? extends AopHandler>> methodAopList,
               List<Class<? extends AopHandler>> globalAopList) {
        this.typeRoute = typeRoute;
        this.methodRoute = methodRoute;
        this.api = api;
        this.method = method;
        this.apiReqMethod = apiReqMethod;
        this.methodAopList = methodAopList;
        this.globalAopList = globalAopList;
        this.apiRoute = apiPathFilter(apiPathFilter(typeRoute)
                + apiPathFilter(methodRoute))
                + "$" + apiReqMethod.getMethod() + "$";
        aopList = new ArrayList<AopHandler>();
        merge();
    }

    public String getApiRoute() {
        return apiRoute;
    }

    public Class<?> getApi() {
        return api;
    }

    public Method getMethod() {
        return method;
    }

    public List<AopHandler> getAopList() {
        return aopList;
    }

    /**
     * 所有拦截器排序
     */
    private void merge() {
        Collections.sort(globalAopList, aopComparator());
        try {
            for (Class<? extends AopHandler> clazz : globalAopList)
                aopList.add(clazz.newInstance());
            for (Class<? extends AopHandler> clazz : methodAopList)
                aopList.add(clazz.newInstance());
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

    }

    /**
     * 拦截器顺序比较器
     * @return
     */
    public Comparator<Class<? extends AopHandler>> aopComparator() {
        return new Comparator<Class<? extends AopHandler>>() {
            public int compare(Class<? extends AopHandler> o1,
                               Class<? extends AopHandler> o2) {
                return o1.getAnnotation(Aop.class).order()
                        - o2.getAnnotation(Aop.class).order();
            }
        };
    }

    /**
     * 过滤Api路径分隔符
     * @param path
     * @return
     */
    private String apiPathFilter(String path) {
        return ("/" + path + "/").replaceAll("/+", "/");
    }

}
